import game
import lepton
import lepton.renderer
import lepton.emitter
import lepton.controller
import math
import pyglet
from pyglet.gl import *


class Weapon:

	def __init__(self):
		self.fired = None

	def fire(self, shooter, target):
		if not self.fired or self.fired[2] < (game.state.time - self.fire_delay):
			if self.range >= (target.center - shooter.center).length():
				target.damage(self.damage)
				self.fired = (shooter.center, target.center, game.state.time)
				return True
		return False

	def draw(self):
		pass

	def update(self, dt):
		pass

	@property
	def fire_delay(self):
		return 1.0 / self.rate_of_fire


class Laser(Weapon):

	def __init__(self):
		Weapon.__init__(self)
		self.sparks = None

	def fire(self, shooter, target):
		if Weapon.fire(self, shooter, target):

			self.sparks = lepton.ParticleGroup(
				controllers=[
					lepton.controller.Lifetime(.8 * self.fire_delay),
					lepton.controller.Movement(damping=0.94),
					lepton.controller.ColorBlender(
						[(0, (1, 1, 1, 1)),
							(.4 * self.fire_delay, (1, 1, 1, 1)),
							(.8 * self.fire_delay, (1, .3, 0, 0))],
						resolution=10)],
				renderer=lepton.renderer.BillboardRenderer())

			spark_emitter = lepton.emitter.StaticEmitter(
				template=lepton.Particle(
					position=tuple(game.state.tactical_handler.map_view.opengl_coordinates(target.center)),
					velocity=(0, 0, 3 * target.size),
					size=(.01 * self.damage, .01 * self.damage, 0)),
				deviation=lepton.Particle(
					velocity=(.2 * target.size, .2 * target.size, target.size),
					size=(.002 * self.damage, .002 * self.damage, 0)))

			spark_emitter.emit(int(math.sqrt(self.damage)), self.sparks)

	def draw(self):
		if self.fired:
			fired_from, fired_to, fired_time = self.fired
			fired_from = game.state.tactical_handler.map_view.opengl_coordinates(fired_from)
			fired_to = game.state.tactical_handler.map_view.opengl_coordinates(fired_to)
			zzz = (game.state.time - fired_time) / (self.fire_delay / 5.0)
			if 0 <= zzz < 1:
				pyglet.graphics.draw(2, pyglet.gl.GL_LINES,
					('v3f',
						(fired_from.x, fired_from.y, fired_from.z,
						fired_to.x, fired_to.y, fired_to.z)),
					('c4f',
						(0, 1, 1, abs(zzz - 1),
						0, 1, 1, zzz)))

		if self.sparks is not None:
			glDisable(GL_DEPTH_TEST)
			tex = pyglet.resource.texture('flare3.png')
			glEnable(tex.target)
			glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_CLAMP)
			glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP)
			glTexParameteri(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
			glTexParameteri(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
			self.sparks.draw()
			glDisable(tex.target)
			glEnable(GL_DEPTH_TEST)

	def update(self, dt):
		if self.sparks is not None:
			self.sparks.update(dt)


class Gun(Weapon):

	def __init__(self):
		Weapon.__init__(self)
		self.spark = None

	def fire(self, shooter, target):
		if Weapon.fire(self, shooter, target):
			# hit spark
			self.spark = lepton.ParticleGroup(
				controllers=[lepton.controller.Lifetime(.5 * self.fire_delay)],
				renderer=lepton.renderer.BillboardRenderer())
			spark_emitter = lepton.emitter.StaticEmitter(
				template=lepton.Particle(
					position=tuple(game.state.tactical_handler.map_view.opengl_coordinates(target.center)),
					size=(.05 * self.damage, .05 * self.damage, 0),
					color=(1, 1, 1, 1)),
				deviation=lepton.Particle(
					position=(.3 * target.size, .3 * target.size, .3 * target.size)))
			spark_emitter.emit(1, self.spark)

	def draw(self):
		if self.spark is not None:
			glDisable(GL_DEPTH_TEST)
			tex = pyglet.resource.texture('flare3.png')
			glEnable(tex.target)
			glTexParameteri(tex.target, GL_TEXTURE_WRAP_S, GL_CLAMP)
			glTexParameteri(tex.target, GL_TEXTURE_WRAP_T, GL_CLAMP)
			glTexParameteri(tex.target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
			glTexParameteri(tex.target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
			self.spark.draw()
			glDisable(tex.target)
			glEnable(GL_DEPTH_TEST)

	def update(self, dt):
		if self.spark is not None:
			self.spark.update(dt)


class Bite(Weapon):

	range = 0.1
	damage = 3
	rate_of_fire = 3


class Gatling(Gun):

	range = 3
	damage = 1
	rate_of_fire = 5


class LaserRifle(Laser):

	range = 6
	damage = 10
	rate_of_fire = 1


class LaserCannon(Laser):

	range = 8
	damage = 50
	rate_of_fire = 0.5

